package com.cf.user.login.filter;


import com.cf.constant.EnumReturnCode;
import com.cf.order.Ordered;
import com.cf.user.login.LocalUserHolder;
import com.cf.user.login.UserSystemProperty;
import com.cf.user.login.model.UserInfo;
import com.cf.user.login.service.TokenManager;
import com.cf.util.RequestUtil;
import com.cf.vo.ResponseVo;
import com.cf.web.RequiredLogin;
import com.cf.web.controller.MvcHandlers;
import com.cf.web.filter.ZmmFilter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.List;

/**
 * boot-awm-LoginFilter
 *
 * @author <a href="2428922347@qq.com">Zhu mingming</a>
 * @info
 * @since 2018/7/6 下午 03:18
 */
@Slf4j
public class LoginFilter extends ZmmFilter implements Ordered {

    @Autowired
    private MvcHandlers mvcHandlers;

    @Autowired
    private TokenManager tokenManager;

    @Autowired
    private UserSystemProperty userSystemProperty;

    public LoginFilter() {
        log.info("实例化登陆检测拦截器");
    }


    @Override
    protected void doInnerFilter(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        // 验证权限
        if (this.checkLogin(request, mvcHandlers.handler(request), response)) {
            filterChain.doFilter(request, response);
            LocalUserHolder.clean();
            return;
        }

        if (mvcHandlers.isJsonResponse(request)) {
            RequestUtil.renderJson(response, ResponseVo.fail(EnumReturnCode.NEED_LOGIN.getCode(), null, "请重新登陆！"));
        } else {
            response.sendRedirect(userSystemProperty.getLoginPage() + "?msg=" + URLEncoder.encode("请重新登陆！", "utf-8"));
        }

    }


    /**
     * 是否有权限
     *
     * @param request
     * @param handler
     * @return
     */
    private boolean checkLogin(HttpServletRequest request, Object handler, HttpServletResponse response) throws IOException {
        if (!needLogin(request, handler))
            return true;

        UserInfo userInfo = tokenManager.userInfo(request);
        if (userInfo == null) {
            return false;
        } else {
            LocalUserHolder.set(userInfo);
        }

        return true;
    }

    private boolean needLogin(HttpServletRequest request, Object handler) {
        if (handler == null) {
            log.info("当前未找到对应的handler，执行严格模式，需要登陆！【{}】，【{}】" + RequestUtil.getIpAddr(request), request.getRequestURL());
            return true;
        }

        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            // 获取方法上的注解
            RequiredLogin requiredLogin = handlerMethod.getMethod().getAnnotation(RequiredLogin.class);
            // 如果方法上的注解为空 则获取类的注解
            if (requiredLogin == null) {
                requiredLogin = handlerMethod.getMethod().getDeclaringClass().getAnnotation(RequiredLogin.class);
            }
            // 如果标记了注解，则判断权限
            if (requiredLogin != null) {
                return true;
            } else {
                return false;
            }
        } else {
            return true;
        }
    }


    @Override
    public int getOrder() {
        return 10;
    }

    @Override
    public List<String> matchPathPatterns() {
        return Arrays.asList("/*");
    }

}
